package com.pp.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pp.common.pojo.Post;
import com.pp.common.pojo.User;
import com.pp.common.vo.SysResult;
import com.pp.web.model.dto.LoginDTO;
import com.pp.web.model.dto.RegisterDTO;
import com.pp.web.service.IPostService;
import com.pp.web.service.IUserService;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;

import static com.pp.common.util.JwtUtils.USERNAME;

@RestController
@RequestMapping("/api/user")
public class UserController extends BaseController {

    @Resource
    private IUserService userService;

    @Resource
    private IPostService postService;

    /**
     * 注册
     * 请求方法: POST
     * 请求URL: http://localhost:8090/api/user/register
     * 请求参数: Signup Form 表单数据 (包括 username, email, password)
     * 返回值: SysResult(responseMap) 响应对象
     */
    @PostMapping("/register")
    public SysResult register(@Valid @RequestBody RegisterDTO registerDTO) {
        User user = userService.register(registerDTO);
        if (ObjectUtils.isEmpty(user)) {
            return SysResult.fail("账号注册失败");
        }
        Map<String, Object> responseMap = new HashMap<>(16);
        responseMap.put("user", user);
        return SysResult.success(responseMap);
    }

    /**
     * 登录
     * 请求方法: POST
     * 请求URL: http://localhost:8090/api/user/login
     * 请求参数: Login Form 表单数据 (包括 username, password 和 rememberMe)
     * 返回值: SysResult(user) 响应对象
     */
    @PostMapping("/login")
    public SysResult login(@Valid @RequestBody LoginDTO loginDTO) {
        String token = userService.login(loginDTO);
        if (ObjectUtils.isEmpty(token)) {
            return SysResult.fail("账号密码不匹配");
        }
        Map<String, String> responseMap = new HashMap<>(16);
        responseMap.put("token", token);
        return SysResult.success("登录成功", responseMap);
    }

    /**
     * 根据 id 查找对应的用户
     * 请求方法: GET
     * 请求URL: http://localhost:8090/api/user/7
     * 请求参数: 用户 id
     * 返回值: SysResult(user) 响应对象
     */
    @GetMapping("/{id}")
    public SysResult getUserById(@PathVariable String id) {
        System.out.println("Entering getUserById method");
        User user = userService.getUserById(id);
        return SysResult.success(user);
    }

    /**
     * 根据 request header 中的 username 查询对应的用户信息
     * 请求方法: GET
     * 请求URL: http://localhost:8090/api/user/info
     * 请求参数: Request Header 中的 "Authorization" 请求头
     * 返回值: SysResult(user) 响应对象
     *
     * 前端调用 getUserInfo 时，没有将 username 作为该方法的参数，因此 username 的值需要
     * 从 token 中获取，每次 axios 拦截器会从 vuex store 中取出 token，添加上 "Bearer "
     * 前缀，以 "Authorization" 请求头的形式发送到后端
     * 在 JwtUtils 类中，我们将从请求头"Authorization" 中解析出来的 username 添加到自定义
     * request 对象的请求头 "USERNAME" 中，通过 @RequestHeader 注解拿到 username 的值
     * 传递给当前方法的 username 参数
     */
    @GetMapping("/info")
    public SysResult getUserByUsernameFromRequestHeader(
        @RequestHeader(value = USERNAME) String username) {
        User user = userService.getUserByUsername(username);
        return SysResult.success(user);
    }

    /**
     * 根据 username 获取用户主页信息
     * 请求方法: GET
     * 请求URL: http://localhost:8090/api/user/username
     * 请求参数: username
     * 返回值: SysResult(responseMap) 响应对象
     */
    @GetMapping("/home/{username}")
    public SysResult getUserByUsername(
            @PathVariable("username") String username,
            @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNum,
            @RequestParam(value = "size", defaultValue = "10") Integer pageSize) {
        Map<String, Object> responseMap = new HashMap<>(16);

        // 查看 username 对应的用户是否存在
        User user = userService.getUserByUsername(username);
        Assert.notNull(user, "用户不存在");

        // 若存在则返回当前用户的所有帖子
        Page<Post> pageResult = postService.page(
                new Page<>(pageNum, pageSize),
                new LambdaQueryWrapper<Post>().eq(Post::getUserId, user.getId())
        );

        // 封装用户信息
        responseMap.put("user", user);
        // 封装帖子信息
        responseMap.put("posts", pageResult);

        // 返回封装了 user 和 posts 的 map
        return SysResult.success(responseMap);
    }

    /**
     * 更新用户信息
     * 请求方法: PUT
     * 请求URL: http://localhost:8090/api/user/update
     * 请求参数: user 对象
     * 返回值: SysResult(user) 响应对象
     */
    @PutMapping("/update")
    public SysResult updateUser(@RequestBody User user) {
        this.userService.updateById(user);
        return SysResult.success(user);
    }

    /**
     * 注销
     * 请求方法: GET
     * 请求URL: http://localhost:8090/api/user/logout
     * 请求参数: 无
     * 返回值: SysResult("注销成功") 响应对象
     */
    @GetMapping("/logout")
    public SysResult logOut() {
        // 仅仅返回一个提示信息即可
        return SysResult.success("注销成功");
    }

}
